home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
NOVA - For the NeXT Workstation
/
NOVA - For the NeXT Workstation.iso
/
SourceCode
/
AdobeExamples
/
NX_ImportAdv
/
NXEPSImageRepSub.m
< prev
next >
Wrap
Text File
|
1992-12-19
|
12KB
|
519 lines
/*
* (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved.
*
* (b) If this Sample Code is distributed as part of the Display PostScript
* System Software Development Kit from Adobe Systems Incorporated,
* then this copy is designated as Development Software and its use is
* subject to the terms of the License Agreement attached to such Kit.
*
* (c) If this Sample Code is distributed independently, then the following
* terms apply:
*
* (d) This file may be freely copied and redistributed as long as:
* 1) Parts (a), (d), (e) and (f) continue to be included in the file,
* 2) If the file has been modified in any way, a notice of such
* modification is conspicuously indicated.
*
* (e) PostScript, Display PostScript, and Adobe are registered trademarks of
* Adobe Systems Incorporated.
*
* (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
* CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
* AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
* ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
* OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
* WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
* WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
* DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
* OF THIRD PARTY RIGHTS.
*/
/*
* NXEPSImageRepSub.m
*
* A subclass of NXEPSImageRep. Enhanced to handle rotation
* and resources.
*
* Version: 2.0
* Author: Ken Fromm
*/
#import "NXEPSImageRepSub.h"
#import <appkit/Font.h>
#import <appkit/Panel.h>
#import <appkit/View.h>
#import <appkit/nextstd.h>
#import <appkit/defaults.h>
#import <objc/List.h>
#import <objc/Storage.h>
#import <objc/hashtable.h>
#import <dpsclient/wraps.h>
#import <stdio.h>
/* Used only for demonstration purposes. */
#import "ImportApp.h"
#import "epsfwraps.h"
@implementation NXEPSImageRepSub
- free
{
if (_tempName)
NX_FREE(_tempName);
return [super free];
}
- writeIncludedFiles:storage;
{
int i, count,
writelen, readlen, includelen, maxlen;
char *readdata, *startdata, *includedata;
NXStream *writestream, *readstream, *includestream;
Inclusion *inclusion;
if (storage && [storage count])
{
readlen = 0;
readdata = NULL;
readstream = NULL;
if (_fileName)
{
readstream = NXMapFile(_fileName, NX_READONLY);
if (readstream)
NXGetMemoryBuffer(readstream, &readdata, &readlen, &maxlen);
}
else
{
readdata = _memory;
readlen = _epsLen;
}
if (readdata && readlen)
{
startdata = readdata;
if (_fileName)
writestream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
else
writestream = NXOpenMemory(NULL, 0, NX_READWRITE);
if (writestream)
{
count = [storage count];
for (i = 0; i < count; i++)
{
inclusion = [storage elementAt:i];
if (inclusion->filename && inclusion->len)
{
writelen = inclusion->offset - (readdata - startdata);
NXWrite(writestream, readdata, writelen);
includestream = NXMapFile(inclusion->filename, NX_READONLY);
if (includestream)
{
NXGetMemoryBuffer(includestream, &includedata,
&includelen, &maxlen);
NXWrite(writestream, includedata, includelen);
}
else
NXWrite(writestream, readdata+inclusion->offset,
inclusion->len);
readdata += writelen + inclusion->len;
readlen -= (writelen + inclusion->len);
}
}
NXWrite(writestream, readdata, readlen);
if (_fileName)
{
_tempName = NXCopyStringBuffer("/tmp/EpsfTempXXXXXX.eps");
NXGetTempFilename(_tempName, 13);
if (_tempName)
NXSaveToFile(writestream, _tempName);
NXCloseMemory(writestream, NX_FREEBUFFER);
}
else
{
NXGetMemoryBuffer(writestream, &_tempMemory,
&_tempEpsLen, &maxlen);
NXCloseMemory(writestream, NX_SAVEBUFFER);
}
}
}
if (readstream)
NXCloseMemory(readstream, NX_FREEBUFFER);
}
return self;
}
/*
* Check to see if the fonts are on the system and only flag
* those not available.
*/
- checkFonts:(Resource *) resource placeIn:(ResourceList *) resourceList
{
id font;
int i, count;
if (resource && resourceList)
{
if (resource->states[RES_NEEDED])
resourceList->types[RES_FONTS] = [resource->states[RES_NEEDED] copy];
else if (!resource->states[RES_SUPPLIED] && resource->states[RES_PRESENT])
resourceList->types[RES_FONTS] = [resource->states[RES_PRESENT] copy];
/*
* There should be an easier way to check for font availability other
* than to create a font object but this will have to do for now.
*/
count = [resourceList->types[RES_FONTS] count];
for (i = count -1; i >= 0; i--)
{
font = [Font newFont:(char *) [resourceList->types[RES_FONTS] objectAt:i] size:12];
if (font)
{
[font free];
[resourceList->types[RES_FONTS] removeObjectAt:i];
}
}
if ([resourceList->types[RES_FONTS] count] == 0)
{
[resourceList->types[RES_FONTS] free];
resourceList->types[RES_FONTS] = NULL;
}
}
return self;
}
- checkFiles:(Resource *) resource placeIn:(ResourceList *) resourceList
{
int i, count;
FILE *file;
if (resource && resourceList)
{
if (resource->states[RES_NEEDED])
resourceList->types[RES_FILES] = [resource->states[RES_NEEDED] copy];
/*
* Try to open the files. If available then remove from the list.
*/
count = [resourceList->types[RES_FILES] count];
for (i = count -1; i >= 0; i--)
{
file = fopen((char *) [resourceList->types[RES_FILES] objectAt:i], "r");
if (file)
{
fclose(file);
[resourceList->types[RES_FILES] removeObjectAt:i];
}
}
if ([resourceList->types[RES_FILES] count] == 0)
{
[resourceList->types[RES_FILES] free];
resourceList->types[RES_FILES] = NULL;
}
}
return self;
}
- checkProcSets:(Resource *) resource placeIn:(ResourceList *) resourceList
{
if (resource && resourceList)
{
if (resource->states[RES_NEEDED])
resourceList->types[RES_PROCSETS] = [resource->states[RES_NEEDED] copy];
}
return self;
}
- checkPatterns:(Resource *) resource placeIn:(ResourceList *) resourceList
{
if (resource && resourceList)
{
if (resource->states[RES_NEEDED])
resourceList->types[RES_PATTERNS] = [resource->states[RES_NEEDED] copy];
}
return self;
}
- checkForms:(Resource *) resource placeIn:(ResourceList *) resourceList
{
if (resource && resourceList)
{
if (resource->states[RES_NEEDED])
resourceList->types[RES_FORMS] = [resource->states[RES_NEEDED] copy];
}
return self;
}
/*
* Fills in the empty resources and inclusions array within the epsf structure.
*/
- (int) getResources:(EpsfStruct *) epsf
{
int maxlen, error;
NXStream *stream;
error = EPSF_INVALIDPS;
if (epsf)
{
stream = NULL;
epsf->filedata = NULL;
if (_fileName)
{
stream = NXMapFile(_fileName, NX_READONLY);
if (stream)
NXGetMemoryBuffer(stream, &epsf->filedata, &epsf->filelen, &maxlen);
}
else
{
epsf->filedata = _memory;
epsf->filelen = _epsLen;
}
if (epsf->filedata)
error = ReadEpsf(epsf);
if (stream)
NXCloseMemory(stream, NX_FREEBUFFER);
}
return error;
}
/*
* Returns the list of unavailableResources.
*
* Returns any resources except for fonts that are marked as needed.
* Check to see if the fonts are on the system and flags only those not
* available. As the other resources move into the realm of system
* resources, this method can check the availability of these resources
* as well.
*
*/
- checkResources:(ResourceList *) resourceList;
{
int error;
EpsfStruct epsf;
bzero(resourceList, sizeof(ResourceList));
error = [self getResources:&epsf];
if (!error)
{
[self checkFonts:&epsf.resources[RES_FONTS] placeIn:resourceList];
[self checkFiles:&epsf.resources[RES_FILES] placeIn:resourceList];
[self checkProcSets:&epsf.resources[RES_PROCSETS] placeIn:resourceList];
[self checkPatterns:&epsf.resources[RES_PATTERNS] placeIn:resourceList];
[self checkForms:&epsf.resources[RES_FORMS] placeIn:resourceList];
[self writeIncludedFiles:epsf.inclusions];
return self;
}
else
Notify("Import Error", ErrorEpsf(error));
return nil;
}
/*
* Used when printing. Add the resources used in this file
* to the list passed in. Only adds the resources that are not
* currently in the resourceDoc structure already.
*/
- addResources:(Resource *) resourceDoc forFile:(NXAtom) fileName
{
id name;
int i, j, k, count;
EpsfStruct epsf;
if (_fileName || fileName)
{
i = RES_SUPPLIED;
if (_fileName)
{
name = (id) _fileName;
if (NXDrawingStatus == NX_COPYING)
i = RES_NEEDED;
}
else
name = (id) fileName;
if (!resourceDoc[RES_FILES].states[RES_PRESENT])
resourceDoc[RES_FILES].states[RES_PRESENT] = [List new];
if (!resourceDoc[RES_FILES].states[RES_NEEDED])
resourceDoc[RES_FILES].states[i] = [List new];
[resourceDoc[RES_FILES].states[RES_PRESENT] addObjectIfAbsent:name];
[resourceDoc[RES_FILES].states[i] addObjectIfAbsent:name];
}
[self getResources:&epsf];
for (i = 0; i < RES_NUMTYPES; i++)
{
for (j = 0; j < RES_NUMSTATES; j++)
{
if (epsf.resources[i].states[j])
{
if (!resourceDoc[i].states[j])
resourceDoc[i].states[j] = [List new];
count = [epsf.resources[i].states[j] count];
for (k = 0; k < count; k++)
[resourceDoc[i].states[j]
addObjectIfAbsent:[epsf.resources[i].states[j] objectAt:k]];
}
}
}
return self;
}
/*
* Overridden to handle any %%IncludeFile. A temporary file or
* memory buffer has been written out that adds the included
* files. This temporary file or memory pointer are swapped for the
* real ones if they exist. The image is drawn and then they are
* returned back. Their is probably a better way but without
* knowing the internals of how this class works its a tenuous
* bet to find one.
*/
- (BOOL) draw
{
BOOL rc = YES;
char *data,
*tempname,
*tempmemory;
int templen, len, maxlen;
NXStream *stream;
templen = 0;
tempname = tempmemory = NULL;
if (_tempName || _tempMemory)
{
if (_fileName)
{
tempname = _fileName;
_fileName = _tempName;
}
else
{
tempmemory = _memory;
templen = _epsLen;
_memory = _tempMemory;
_epsLen = _tempEpsLen;
}
}
/*************************************************************
* The first case of the if-else statement is only to show
* what can happen when a separate context is not used.
* The imaging should be done with the draw method
* because it installs a separate context.
**************************************************************/
if (![NXApp contextFlag])
{
PStranslate(-_bBoxOrigin.x, -_bBoxOrigin.y);
if (_fileName && !_repFlags.dataLoaded)
{
stream = NXMapFile(_fileName, NX_READONLY);
if (stream)
NXGetMemoryBuffer(stream, &data, &len, &maxlen);
}
else
{
data = _memory;
len = _epsLen;
}
PSWBeginEpsf();
DPSWritePostScript(DPSGetCurrentContext(), data, len);
PSWEndEpsf();
}
else
rc = [super draw];
if (_tempName || _tempMemory)
{
if (_fileName)
{
_fileName = tempname;
}
else
{
_memory = tempmemory;
_epsLen = templen;
}
}
return rc;
}
/*
* Draws the EPS file. Positions it appropriately, scaling and rotating
* it according to the arguments passed in. The rotation is in degrees.
*/
- (BOOL) drawIn:(NXRect *) r with:(float) rotation
{
BOOL error;
NXRect original;
error = NO;
if (NXDrawingStatus == NX_COPYING)
{
original.origin = _bBoxOrigin;
original.size = size;
if (_fileName)
{
WriteEpsfIllustratorBeg(r, &original, rotation, _fileName);
WriteEpsfIllustratorInclude(_fileName);
WriteEpsfIllustratorEnd();
}
else
{
WriteEpsfIllustratorBeg(r, &original, rotation, NULL);
DPSWritePostScript(DPSGetCurrentContext(), _memory, _epsLen);
WriteEpsfIllustratorEnd();
}
}
else
{
PSgsave();
PStranslate(r->origin.x, r->origin.y);
PSrotate(rotation);
PSscale(r->size.width/size.width, r->size.height/size.height);
error = [self draw];
PSgrestore();
}
return error;
}
@end